package com.score;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import java.util.ArrayList;

/**
 * Created by Roger on 2019/6/23.
 */

public class RLyricView extends View {
    private int POINT_PADDING, POINT_WIDTH;
    private int mNoramlTextSize, mChooseTextSize;
    private int mTopMargin;
    private ArrayList<RLyricReader.LyricObject> mLrcList;
    private int mWidth, mHeight;
    private Paint mPaint;
    private long mMs = 0;
    private int mOffsetY = 0;
    private LinearGradient mGradient;
    private boolean mIsScroll = false;
    private float mPreSt;

    public RLyricView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setAntiAlias(true);
        mPaint.setColor(getResources().getColor(android.R.color.darker_gray));
        mPaint.setStrokeCap(Paint.Cap.ROUND);
    }

    public void init() {
        try {
            mLrcList = RLyricReader.readLrc(getContext());
            postInvalidate();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void setMs(long ms) {
        mMs = ms;
        postInvalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
        POINT_WIDTH = POINT_PADDING = mWidth / 35;
        mPaint.setStrokeWidth(POINT_WIDTH);
        mTopMargin = POINT_WIDTH * 3;
        mNoramlTextSize = mWidth / 20;
        mChooseTextSize = mWidth / 18;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        float offsetY = mOffsetY;
        long diff = mLrcList.get(0).startTime - mMs;
        if (diff <= 3000 && diff >= 0) {
            mGradient = new LinearGradient((mWidth - 3 * POINT_WIDTH - 2 * POINT_PADDING) / 2, 0, mWidth / 2 + 1.5f * POINT_WIDTH + POINT_PADDING, 0, new int[]{
                    Color.RED, Color.RED, getResources().getColor(android.R.color.darker_gray), getResources().getColor(android.R.color.darker_gray)}, new float[]{0, 1 - (1f * diff / 3000), 1 - (1f * diff / 3000), 1},
                    Shader.TileMode.CLAMP);
            mPaint.setShader(mGradient);
        } else {
            mPaint.setShader(null);
        }
        for (int i = 0; i < 3; i++) {
            float x = (mWidth - 3 * POINT_WIDTH - 2 * POINT_PADDING) / 2 + i * (POINT_PADDING + POINT_WIDTH);
            float y = POINT_WIDTH / 2;
            canvas.drawPoint(x + POINT_WIDTH / 2, y + offsetY, mPaint);
        }

        Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
        for (int i = 0, size = mLrcList.size(); i < size; i++) {
            RLyricReader.LyricObject lyricWord = mLrcList.get(i);
            mPaint.setTextSize(mNoramlTextSize);
            float y = (i + 1) * mTopMargin + (fontMetrics.bottom - fontMetrics.ascent) / 2;
            mPaint.setTextSize(mNoramlTextSize);
            Rect bounds = new Rect();
            mPaint.getTextBounds(lyricWord.content.toString(), 0, lyricWord.content.length(), bounds);
            int contentLen = bounds.width();
            float x = (mWidth - contentLen) / 2;
            if (mMs >= lyricWord.startTime && (i < size - 1 ? mMs < mLrcList.get(i + 1).startTime : true)) {
                float st = 0;
                for (int j = 0, jsize = lyricWord.words.size(); j < jsize; j++) {
                    RLyricReader.LyricObject.Word word = lyricWord.words.get(j);
                    if (mMs >= lyricWord.startTime + word.startTime && (j != jsize - 1 ? mMs <= lyricWord.startTime + word.startTime + word.duration : true)) {
                        st = 1f * j / jsize + 1f * (mMs - lyricWord.startTime - word.startTime) / word.duration / jsize;
                        mPreSt = st;
                        break;
                    } else {
                        st = mPreSt;
                    }
                }
                mPaint.setTextSize(mChooseTextSize);
                y = (i + 1) * mTopMargin + (fontMetrics.bottom - fontMetrics.ascent) / 2;
                mPaint.getTextBounds(lyricWord.content.toString(), 0, lyricWord.content.length(), bounds);
                contentLen = bounds.width();
                x = (mWidth - contentLen) / 2;
                mGradient = new LinearGradient(x, 0, x + contentLen, 0,
                        new int[]{Color.RED, Color.RED, getResources().getColor(android.R.color.darker_gray), getResources().getColor(android.R.color.darker_gray)},
                        new float[]{0, st, st, 1},
                        Shader.TileMode.CLAMP);
                mPaint.setShader(mGradient);
                canvas.drawText(lyricWord.content.toString(), x, y + offsetY, mPaint);
                if (y + offsetY > mHeight / 2 && !mIsScroll) {
                    mIsScroll = true;
                    scroll(y + offsetY - mHeight / 2);
                }
            } else {
                mPaint.setShader(null);
                canvas.drawText(lyricWord.content.toString(), x, y + offsetY, mPaint);
            }
        }
    }

    private void scroll(final float diff) {
        new Thread() {
            @Override
            public void run() {
                super.run();
                float xDiff = diff;
                while (xDiff > 0) {
                    xDiff -= 3;
                    mOffsetY -= 3;
                    postInvalidate();
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                mIsScroll = false;
            }
        }.start();
    }
}
